/*
 * SocketTypes.h
 *
 *  Created on: May 29, 2013
 *      Author: Lucifer
 */

#ifndef __BFX_SOCKETTYPES_H__
#define __BFX_SOCKETTYPES_H__

#ifdef	_WIN32

typedef	int	SOCKLEN_T;

#else	//	_WIN32
#include <unistd.h>

#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>

typedef	socklen_t	SOCKLEN_T;
typedef	int			SOCKET;
typedef	struct sockaddr	SOCKADDR;
typedef	struct sockaddr_in	SOCKADDR_IN;

#define	INVALID_SOCKET	(SOCKET)(~0)
#define	SOCKET_ERROR	(-1)

#define	closesocket	close
#define	ioctlsocket	ioctl

#endif	//	!_WIN32

/**
 *  @namespace BFX
 *  The base namespace of our framework.
 */
namespace BFX
{

/**
 * Specifies the addressing scheme that an instance of the socket can use.
 */
enum SocketAddressFamily
{

	/// Unknown address family.
	SocketAddressFamily_Unknown			= -1,

	/// Unspecified address family.
	SocketAddressFamily_Unspecified		= 0,	// AF_UNSPEC

	/// Unix local to host address.
	SocketAddressFamily_Unix			= 1,	// AF_UNIX, AF_LOCAL

	/// Address for IP version 4. UDP, TCP, etc.
	SocketAddressFamily_InterNetwork	= 2,	// AF_INET

	/// ARPANET IMP address.
	SocketAddressFamily_ImpLink			= 3,	// AF_IMPLINK

	/// Address for PUP protocols.
	SocketAddressFamily_Pup				= 4,	// AF_PUP

	/// Address for MIT CHAOS protocols.
	SocketAddressFamily_Chaos			= 5,	// AF_CHAOS

	/// Address for Xerox NS protocols.
	SocketAddressFamily_NS				= 6,	// AF_NS

	/// IPX or SPX address.
	SocketAddressFamily_Ipx				= SocketAddressFamily_NS,

	/// Address for ISO protocols.
	SocketAddressFamily_Iso				= 7,	// AF_ISO

	// TODO: More address families.
};

/**
 * Specifies the type of socket that an instance of the socket represents.
 */
enum SocketType
{
	/// Unknown socket type.
	SocketType_Unknown		= -1,

	/// Stream (connection) socket.
	SocketType_Stream		= 1,	// SOCK_STREAM

	/// Datagram (connectionless) socket.
	SocketType_Dgram		= 2,	// SOCK_DGRAM

	/// Raw socket.
	SocketType_Raw			= 3,	// SOCK_RAW

	/// Reliably-delivered message.
	SocketType_Rdm			= 4,	// SOCK_RDM

	/// Sequential packet socket.
	SocketType_Seqpacket	= 5,	// SOCK_SEQPACKET

	// TODO: GNU extensions
};

/**
 * Specifies the protocols that the socket supports.
 */
enum SocketProtocolType
{
	/// Unknown protocol type
	SocketProtocolType_Unknown        = -1,

	/// Dummy protocol for TCP
	SocketProtocolType_IP					= 0,	// IPPROTO_IP

	/// IPv6 Hop-by-Hop options
	SocketProtocolType_IPv6HopByHopOptions	= 0,	// IPPROTO_HOPOPTS

	/// Internet Control Message Protocol
	SocketProtocolType_Icmp					= 1,	// IPPROTO_ICMP

	/// Internet Gateway Management Protocol
	SocketProtocolType_Igmp					= 2,	// IPPROTO_IGMP

	/// IPIP tunnels (older KA9Q tunnels use 94)
	SocketProtocolType_IPv4					= 4,	// IPPROTO_IPIP

	/// Transmission Control Protocol
	SocketProtocolType_Tcp					= 6,	// IPPROTO_TCP

	// TODO: IPPROTO_EGP

	/// PUP protocol
	SocketProtocolType_Pup					= 12,	// IPPROTO_PUP

	/// User Datagram Protocol
	SocketProtocolType_Udp					= 17,	// IPPROTO_UDP

	/// XNS IDP protocol
	SocketProtocolType_Idp					= 22,	// IPPROTO_IDP

	/// IPv6 header
	SocketProtocolType_IPv6					= 41,	// IPPROTO_IPV6

	/// IPv6 Routing header
	SocketProtocolType_IPv6RoutingHeader	= 43,	// IPPROTO_ROUTING

	/// IPv6 fragmentation header
	SocketProtocolType_IPv6FragmentHeader	= 44,	// IPPROTO_FRAGMENT

	/// encapsulating security payload
	SocketProtocolType_IPSecEncapsulatingSecurityPayload	= 50,	// IPPROTO_ESP

	/// authentication header
	SocketProtocolType_IPSecAuthenticationHeader	= 51,	// IPPROTO_AH

	/// ICMPv6
	SocketProtocolType_IcmpV6				= 58,	// IPPROTO_ICMPV6

	/// IPv6 no next header
	SocketProtocolType_IPv6NoNextHeader		= 59,	// IPPROTO_NONE

	/// IPv6 Destination options
	SocketProtocolType_IPv6DestinationOptions	= 60,	// IPPROTO_DSTOPTS

	/// Raw IP packets
	SocketProtocolType_Raw					= 255,	// IPPROTO_RAW
};

/**
 * Defines the polling modes for the Socket::Poll method.
 */
enum SocketPollMode
{
	/// Poll the read status of a socket.
	SocketPollMode_Read		= 0,	//

	/// Poll the write status of a socket.
	SocketPollMode_Write	= 1,	//

	/// Poll the error status of a socket.
	SocketPollMode_Error	= 2,	//
};

/**
 * Defines socket option levels for the Socket::SetSocketOption and Socket::GetSocketOption methods
 */
enum SocketOptionLevel
{
	/// Indicates socket options apply to the socket itself.
	SocketOptionLevel_Socket	= 0xffff,

	/// Indicates socket options apply to IP sockets.
	SocketOptionLevel_IP		= SocketProtocolType_IP,

	/// Indicates socket options apply to Tcp sockets.
	SocketOptionLevel_Tcp		= SocketProtocolType_Tcp,

	/// Indicates socket options apply to Udp sockets.
	SocketOptionLevel_Udp		= SocketProtocolType_Udp,
};

/**
 * Provides constant values for socket messages.
 */
enum SocketFlags
{
	/// SocketFlags_None
	SocketFlags_None				= 0,

	/// SocketFlags_OutOfBand
	SocketFlags_OutOfBand			= 0x1,	// MSG_OOB

	/// SocketFlags_Peek
	SocketFlags_Peek				= 0x2,	// MSG_PEEK

	/// SocketFlags_DontRoute
	SocketFlags_DontRoute			= 0x4,	// MSG_DONTROUTE

	/// SocketFlags_MaxIOVectorLength
	SocketFlags_MaxIOVectorLength	= 16,	// MSG_MAXIOVLEN
};

enum SocketIOControlCode
{
};

/**
 * Defines socket option names.
 */
enum SocketOptionName
{
	//
	// Option flags per-socket.
	//

	/// Record debugging information.
	SocketOptionName_Debug					= 0x0001,			// SO_DEBUG

	/// Socket is listening.
	SocketOptionName_AcceptConnection		= 0x0002,			// SO_ACCEPTCONN

	/// Allows the socket to be bound to an address that is already in use.
	SocketOptionName_ReuseAddress			= 0x0004,			// SO_REUSEADDR

	/// Send keep-alives.
	SocketOptionName_KeepAlive				= 0x0008,			// SO_KEEPALIVE

	/// Do not route, send directly to interface addresses.
	SocketOptionName_DontRoute				= 0x0010,			// SO_DONTROUTE

	/// Permit sending broadcast messages on the socket.
	SocketOptionName_Broadcast				= 0x0020,			// SO_BROADCAST

	/// Bypass hardware when possible.
	SocketOptionName_UseLoopback			= 0x0040,			// SO_USELOOPBACK

	/// Linger on close if unsent data is present.
	SocketOptionName_Linger					= 0x0080,			// SO_LINGER

	/// Receives out-of-band data in the normal data stream.
	SocketOptionName_OutOfBandInline		= 0x0100,			// SO_OOBINLINE

	/// Close socket gracefully without lingering.
	SocketOptionName_DontLinger				= ~SocketOptionName_Linger,		// SO_DONTLINGER

	/// Enables a socket to be bound for exclusive access.
	SocketOptionName_ExclusiveAddressUse	= ~SocketOptionName_ReuseAddress,	// disallow local address reuse

	//
	// Additional options.
	//

	/// Specifies the total per-socket buffer space reserved for sends. This is unrelated to the maximum message size or the size of a TCP window.
	SocketOptionName_SendBuffer				= 0x1001,			// SO_SNDBUF

	/// Send low water mark.
	SocketOptionName_ReceiveBuffer			= 0x1002,			// SO_RCVBUF

	/// Specifies the total per-socket buffer space reserved for receives. This is unrelated to the maximum message size or the size of a TCP window.
	SocketOptionName_SendLowWater			= 0x1003,			// SO_SNDLOWAT

	/// Receive low water mark.
	SocketOptionName_ReceiveLowWater		= 0x1004,			// SO_RCVLOWAT

	/// Send timeout.
	SocketOptionName_SendTimeout			= 0x1005,			// SO_SNDTIMEO

	/// Receive timeout.
	SocketOptionName_ReceiveTimeout			= 0x1006,			// SO_RCVTIMEO

	/// Get error status and clear.
	SocketOptionName_Error					= 0x1007,			// SO_ERROR

	/// Get socket type.
	SocketOptionName_Type					= 0x1008,			// SO_TYPE


	// Maximum queue length that can be specified by Listen.
	// TODO: SocketOptionName_MaxConnections          = 0x7fffffff,		// Maximum queue length specifiable by listen.
	// TODO: More options
};

/**
 * @brief Defines constants that describes what types of operation will no longer be allowed.
 * These constants only used by the BFX::REFSocket::Shutdown method.
 */
enum SocketShutdown
{
	/// Shutdown sockets for receive.
	SocketShutdown_Receive	= 0x00,

	/// Shutdown socket for send.
	SocketShutdown_Send		= 0x01,

	/// Shutdown socket for both send and receive.
	SocketShutdown_Both		= 0x02,
};

}	//	namespace BFX

#endif /* __BFX_SOCKETTYPES_H__ */
